library(RGtk2)
library(rgl)

# positions x y z rayon color des 1000 spheres, générés aléatoirement
.datac<-list(x=rnorm(1000),y=rnorm(1000),z=rnorm(1000),radius=runif(1000),color=rainbow(1000))
# environnement qui contiendra les variables globales
# a noter que datac aurait pu etre stocké dans cet environnement
.structure <- new.env()

# bouton 1 qui permet de faire spawn la fenetre
fn_btn_1 <-function(button,user.data){
	# ouverture de la fenêtre rgl n1 dont on stocke l'id dans idfen de l'env
	.structure$idfen1<-open3d()
	# on stocke dans isfocus l'id de la fenêtre actuellement active
	# qui est celle avec laquelle l'utilisateur pourra interagir
	.structure$isfocus<-.structure$idfen1
	# on stocke un booleen qui permet simplement d'indiquer si une ou
	# deux fenetres sont actuellement ouvertes
	.structure$fen2isopen = FALSE
	rgl.bg(color="black") # fond noir
	# spawn des spheres d'apres les données de datac
	rgl.spheres(.datac$x,.datac$y,.datac$z,.datac$radius,.datac$color)
	# on initialise le vecteur keep qui va contenir les elements de datac 
	# qui sont selectionnés
	.structure$keep2<-seq(length = 1000,by = FALSE)
}

# bouton 2 qui permet d'activer la selection
# l'evenement se produira une fois
fn_btn_2 <-function(button,user.data){
	# si la fenetre 1 est active cela signifie qu'il n'y a qu'une seule
	# fenetre active. Le bouton 3 n'a pas encore été sollicité
	if(.structure$isfocus == .structure$idfen1)
		# on s'assure que la fenetre sur laquelle on travaille est bien la 1
		rgl.set(.structure$idfen1)
	# sinon cela signifie qu'il y a 2 fenetres actives puisque la fenetre 2
	# ne devient active qu'apres l'evenement du bouton 3
	else if(.structure$isfocus == .structure$idfen2)
		# on s'assure que la fenetre sur laquelle on travaille est bien la 2
		rgl.set(.structure$idfen2)

	# on stocke dans f le vecteur d'elements selectionnes
	f<-rgl.select3d()
	# en comparant les elements présent dans f et l'ensemble des elements
	# généré dans datac, nous arrivons à stocker dans keep un vecteur de 
	# boolens :
	# - TRUE si l'element corespondant de datac est dans la selection
	# - FALSE sinon
	.structure$keep2  <- f(.datac$x,.datac$y,.datac$z)

	# safe va contenir le nombre d'elements non selectionnés
	safe <- .structure$keep2[.structure$keep2 == FALSE]
	# si le nombre d'elements non selectionnés est différent du nombre 
	# d'elements total on passe à la suite
	# -> gestion du probleme de selection d'une region vide
	# si c'est le cas on ignore l'evenement
	if(length(safe) != length(.structure$keep2[]))
	{

		# si la fenetre 2 est fermée cela signifie que le bouton 3 n'a pas
		# ete sollicité : elements selectionnés et elements non selectionnés
		# sont dans la même fenetre
		if(.structure$fen2isopen == FALSE)
		{
			# on vide la scène rgl de tout les elements qui s'y trouvaient
			rgl.pop()
			# on fait réapparaitre les spheres de datac si celle-ci sont
			# présentes dans keep, cad qu'elle ont été sélectionnées. 
			# Leur couleur imposée localement est rouge.
			rgl.spheres(.datac$x[.structure$keep2],.datac$y[.structure$keep2],.datac$z[.structure$keep2],.datac$radius[.structure$keep2],color="red")
			# les autres spheres de datac, celles qui ne sont pas
			# sélectionnées, sont affichées avec leurs couleurs générées aléatoirement
			rgl.spheres(.datac$x[!.structure$keep2],.datac$y[!.structure$keep2],.datac$z[!.structure$keep2],.datac$radius[!.structure$keep2],.datac$color[!.structure$keep2])
		}
		
		# si la fenetre 2 est ouverte : le bouton 3 a donc ete sollicité
		# et les elements selectionnés ne sont pas dans la meme fenetre
		# que les elements non selectionnes
		else
		{
			
			# Les elements selectionnes seront dans la fenetre 1 
			rgl.set(.structure$idfen1)
			# on fait réapparaitre les spheres de datac si celle-ci sont
			# présentes dans keep, cad qu'elle ont été sélectionnées.
			# Leur couleur imposée localement est rouge.
			rgl.spheres(.datac$x[.structure$keep2],.datac$y[.structure$keep2],.datac$z[.structure$keep2],.datac$radius[.structure$keep2],color="red")
			
			# On passe la fenetre 2 en active afin qu'elle contienne les 
			# elements non selectionnes
			rgl.set(.structure$idfen2)
			# on vide les elements de la fenetre 2
			rgl.pop()
			# les autres spheres de datac, celles qui ne sont pas
			# sélectionnées, sont affichées avec leurs couleurs générées aléatoirement
			rgl.spheres(.datac$x[!.structure$keep2],.datac$y[!.structure$keep2],.datac$z[!.structure$keep2],.datac$radius[!.structure$keep2],.datac$color[!.structure$keep2])	

		}
	}
	else
		print("selection invalide")
	
}

# evenement du bouton 3 qui permet de séparer les elements selectionnés des
# elements non selectionnes
fn_btn_3<-function(button,user.data)
{
	safe <- .structure$keep2[.structure$keep2 == FALSE]
	if(length(safe) != length(.structure$keep2[]))
	{
		# on passe la fenetre 1 en active. Celle-ci contiendra
		rgl.set(.structure$idfen1)
		# on vide la fenetre 1 
		rgl.pop()
		# on fait réapparaitre les spheres de datac si celle-ci sont
		# présentes dans keep, cad qu'elle ont été sélectionnées.
		# Leur couleur imposée localement est rouge.
		rgl.spheres(.datac$x[.structure$keep2],.datac$y[.structure$keep2],.datac$z[.structure$keep2],.datac$radius[.structure$keep2],color="red")
		
		# Si la fenetre 2 est fermee c'est que nous sommes dans cet
		# evenement pour la premiere fois. Nous ouvrons la fenetre 2
		# et nous stockons sont id dans idfen2. Dans les 2 cas
		# la fenetre 2 devient la fenetre active
		if(.structure$fen2isopen == FALSE)
			.structure$idfen2<-open3d()
		else 
			rgl.set(.structure$idfen2)
		# on enregistre que la fenetre 2 est ouverte
		.structure$fen2isopen<-TRUE 
		# on s'assusre que la fenetre active est maintenant la fenetre 2
		.structure$isfocus<-.structure$idfen2
		rgl.set(.structure$idfen2)

		rgl.bg(color="black")
		# les autres spheres de datac, celles qui ne sont pas sélectionnées,
		# sont affichées avec leurs couleurs générées aléatoirement
		rgl.spheres(.datac$x[!.structure$keep2],.datac$y[!.structure$keep2],.datac$z[!.structure$keep2],.datac$radius[!.structure$keep2],.datac$color[!.structure$keep2])	
	}
	

}



fenetre = gtkWindow()
fenetre$title="Test spheres"
superpanel = gtkVBoxNew(FALSE,8)
frame=gtkFrameNew()
fenetre$add(frame)
frame$add(superpanel)
# Add button
	the.buttons <- gtkHButtonBoxNew()
	the.buttons$setBorderWidth(5)
	the.buttons$setLayout("spread")
the.buttons$setSpacing(20)
	superpanel$add(the.buttons)
	btn1 = gtkButton("Spawn")
	btn2 = gtkButton("Select")
	btn3 = gtkButton("Show 2 scenes")
	gSignalConnect(btn1,"clicked",fn_btn_1)
	gSignalConnect(btn2,"clicked",fn_btn_2)
	gSignalConnect(btn3,"clicked",fn_btn_3)
the.buttons$packStart(btn1,FALSE,FALSE,0)
the.buttons$packStart(btn2,FALSE,FALSE,0)
the.buttons$packStart(btn3,FALSE,FALSE,0)
